#include <iostream>
#include <list>
#include <string>
#include <ext/hash_map>
#include "URL.h"
#include "TimedURL.h"
#include "Dominio.h"
#include "Manager.h"
#include "../classes_dados/Hasher.h"
#include "DownloadBeta.h"

using namespace std;

const uint Manager::maxWaitListSize = 500;
const uint Manager::maxReadyListSize = 500;

void Manager::setList(std::list <URL> _urlList){
	urlList =_urlList;
}

string Manager::getRobots(string domain) {
	DownloadBeta downloader;
	cout << "Puxando o robots.txt do dominio " << domain << endl;
	downloader.setURL(domain);
	return downloader.getRobot();
}

void Manager::populateDictionaryMap(){
	URL url_simples;	
	
	string robots;
	time_t tempo;
	
	URLFeliz feliz_teste;
	
	while (!urlList.empty()) {
		//retira URL da lista
		url_simples = urlList.front();
		urlList.pop_front();
		
		uint hash = Hasher::simpleHash(url_simples.get_dominio());
	
		if(map[hash].getName() == ""){
			robots = getRobots(url_simples.get_dominio());
			cout << "ROBOTS:" << endl << robots << endl;
			time(&tempo);
			Dominio dominio_teste(url_simples.get_dominio(), robots, tempo, false);
			map[hash] = dominio_teste;
			dictionary.push_back(url_simples.get_dominio());
		}
		feliz_teste.setProtocol(url_simples.get_protocol());
		feliz_teste.setPath(url_simples.get_path());
		map[hash].insertNextURL(feliz_teste);
	}
}


void Manager::printDictionaryMapInfo(){
	cout << "Total de Dominios: " << dictionary.size() << endl << endl;
	int links = 0;
	
	list<string>::const_iterator it;
	for(it = dictionary.begin(); it != dictionary.end(); it++ ) {
		cout << "Dominio: " << map[ Hasher::simpleHash( *it ) ].getName() <<  endl;
		links += (map[ Hasher::simpleHash( *it ) ].getURLList()).size();
		cout << "Total de URLs: " <<  (map[ Hasher::simpleHash( *it ) ].getURLList()).size() << endl << endl;
	}
	
	cout << endl << "Total de links: " << links << endl;
}

void Manager::populateWaitList() {
//	TimedURL t1("", "", 5);
//	TimedURL t2("a", "a", 12);
//	TimedURL t3("b", "b", 3);
//	TimedURL t4("c", "c", 91);
//
//	waitList.push(t1);
//	waitList.push(t2);
//	waitList.push(t3);
//	waitList.push(t4);
//	
//	while (!waitList.empty())
//	  {
//	     cout << " oi " << waitList.top().getProtocol();
//	     waitList.pop();
//	  }
	list<string>::const_iterator it;
	Dominio dominio;
	TimedURL timedURL;
	it = dictionary.begin();
	while( it != dictionary.end() && waitList.size() < maxWaitListSize ) {
		timedURL = map[ Hasher::simpleHash( *it ) ].getNextURL();
		if (!timedURL.isValid()) {
			it++;
			continue;
		}
		waitList.push(timedURL);
		it++;
	}
}


void Manager::printWaitList() {
	priority_queue<TimedURL, std::vector<TimedURL>, TimeComparison > copia = waitList;
	if (waitList.empty())
		cout << "lista wait vazia" << endl;
	while (!copia.empty())
	{
		cout << " oi " << copia.top().getDomain() << copia.top().getPath() << endl;//"\t\t\t\t\t  t= " << copia.top().getTimestamp() << endl;
		copia.pop();
	}
}

void Manager::populateReadyList() {
	time_t now;
	time(&now);
	TimedURL timedURL;
	URL url;
	while (!waitList.empty() && readyList.size() < maxReadyListSize) {
		timedURL = waitList.top();
		if (timedURL.getTimestamp() < now) {
			waitList.pop();
			url = timedURL.toURL();
			readyList.push_back(url);
		}
		else
			break;
	}
}

void Manager::updateDomain(string dominio) {
	time_t now;
	time(&now);
	uint hash = Hasher::simpleHash(dominio);
	map[hash].updateTimestamp(now);
}

